package com.bosssoft.cloud.wechat.core.api.impl;

import com.bosssoft.cloud.wechat.core.api.SignatureService;
import com.bosssoft.cloud.wechat.core.bean.signature.WxAccessToken;
import com.bosssoft.cloud.wechat.core.bean.signature.WxJsapiTicket;
import com.bosssoft.cloud.wechat.core.infra.config.WxConfig;
import com.bosssoft.cloud.wechat.core.infra.enums.WxApiUrl;
import com.bosssoft.cloud.wechat.core.infra.util.WxSignatureUtil;
import com.bosssoft.cloud.wechat.infrastructure.client.OkClient;
import com.bosssoft.cloud.wechat.infrastructure.enums.ErrEnum;
import com.bosssoft.cloud.wechat.infrastructure.util.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

import static com.bosssoft.cloud.wechat.infrastructure.constant.WxKeywordConsts.*;

/**
 * TODO 对所有微信返回做切面
 * <p>
 * TODO 未来给OkHttpUtil添加一个方法：
 * 传入WxApiUrl，改造enum添加"type"属性，方法自动识别类型，自动拼接并调用
 *
 * @author wcy create on 2021/6/23 15:04 下午
 */
@Slf4j
@Service
public class SignatureServiceImpl implements SignatureService {

    @Resource
    private WxConfig wxConfig;
    @Resource
    private RedisTemplate<Object, Object> redisTemplate;
    @Resource
    private OkClient okClient;

    @Override
    public String getAccessToken() {
        // 若之前access_token有存入redis，则直接获取并使用
        String accessToken = (String) redisTemplate.opsForValue().get(WX_ACCESS_TOKEN);
        return accessToken == null ? getAccessToken(wxConfig.getMpConfig().getMpAppId(), wxConfig.getMpConfig().getMpAppSecret()) : accessToken;
    }

    @Override
    public String getAccessToken(String appid, String secret) {
        WxAccessToken res = okClient.newClient(WxAccessToken.class)
                .runWx(WxApiUrl.Signature.GET_ACCESS_TOKEN_URL, appid, secret)
                .execute();
        Assert.isTrue(res.getErrcode() == null || res.getErrcode().equals(WX_RESULT_SUCCESS), ErrEnum.C0621, res.toString());
        redisTemplate.opsForValue().set(WX_ACCESS_TOKEN, res.getAccessToken(), WX_REDIS_TIMEOUT_COMMON, TimeUnit.MINUTES);
        return res.getAccessToken();
    }

    @Override
    public String getTicket() {
        // 若之前jsapi_ticket有存入redis，则直接获取并使用
        String ticket = (String) redisTemplate.opsForValue().get(WX_JSAPITICKET);
        return ticket == null ? getTicket(getAccessToken()) : ticket;
    }

    @Override
    public String getTicket(String accessToken) {
        WxJsapiTicket res = okClient.newClient(WxJsapiTicket.class)
                .runWx(WxApiUrl.Signature.GET_TICKET_URL, accessToken)
                .execute();
        Assert.isTrue(res.getErrcode().equals(WX_RESULT_SUCCESS), ErrEnum.C0622, res.toString());
        redisTemplate.opsForValue().set(WX_JSAPITICKET, res.getTicket(), WX_REDIS_TIMEOUT_COMMON, TimeUnit.MINUTES);
        return res.getTicket();
    }

    @Override
    public String getSignature(String timestamp, String noncestr, String url) {
        return WxSignatureUtil.getSignature(getTicket(), noncestr, timestamp, url);
    }
}
